package com.cosmoplat.xikai.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cosmoplat.xikai.business.config.producLine.LocationConfig;
import com.cosmoplat.xikai.business.domain.BaseDispatchTask;
import com.cosmoplat.xikai.business.domain.BaseProductInfo;
import com.cosmoplat.xikai.business.domain.ProductQualificationRate;
import com.cosmoplat.xikai.business.domain.dto.scada.DeviceFaultDto;
import com.cosmoplat.xikai.business.domain.mes.req.MesFinishTaskRequest;
import com.cosmoplat.xikai.business.domain.mes.req.MesMaterialDistributionRequest;
import com.cosmoplat.xikai.business.domain.mes.result.ActualProductionPlanning;
import com.cosmoplat.xikai.business.domain.mes.result.MesResult;
import com.cosmoplat.xikai.business.domain.vo.ProductTaskVo;
import com.cosmoplat.xikai.business.domain.vo.TaskForCreateProductVo;
import com.cosmoplat.xikai.business.service.BaseDispatchTaskService;
import com.cosmoplat.xikai.business.mapper.BaseDispatchTaskMapper;
import com.cosmoplat.xikai.business.service.BaseProductInfoService;
import com.cosmoplat.xikai.business.service.MesRequestService;
import com.cosmoplat.xikai.common.core.domain.BaseEntity;
import com.cosmoplat.xikai.common.core.domain.model.LoginUser;
import com.cosmoplat.xikai.common.enums.DelFlagEnum;
import com.cosmoplat.xikai.common.enums.business.TaskPlanStatusEnum;
import com.cosmoplat.xikai.common.utils.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 22047582
 * @description 针对表【base_dispatch_task】的数据库操作Service实现
 * @createDate 2025-01-07 13:51:30
 */
@Slf4j
@Service
public class BaseDispatchTaskServiceImpl extends ServiceImpl<BaseDispatchTaskMapper, BaseDispatchTask>
        implements BaseDispatchTaskService {

    @Autowired
    private LocationConfig locationConfig;

    @Autowired
    private MesRequestService mesRequestService;
    @Autowired
    private BaseProductInfoService baseProductInfoService;

    @Override
    public BaseDispatchTask getByMesTaskId(String taskId) {
        QueryWrapper<BaseDispatchTask> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(BaseDispatchTask::getTaskId, taskId)
                .eq(BaseDispatchTask::getIsDelete, DelFlagEnum.NORMAL.getCode());
        return getOne(queryWrapper);
    }

    @Override
    public List<ProductTaskVo> queryProductionPlanList(QueryWrapper queryDTO) {
        return this.getBaseMapper().queryProductionPlanList(queryDTO);
    }

    @Override
    public BaseDispatchTask getByTaskId(String taskId) {
        QueryWrapper<BaseDispatchTask> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(BaseDispatchTask::getTaskId, taskId)
                .eq(BaseDispatchTask::getIsDelete, DelFlagEnum.NORMAL.getCode());
        return getOne(queryWrapper);
    }

    @Override
    public BaseDispatchTask getDoingTask() {
        QueryWrapper<BaseDispatchTask> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(BaseDispatchTask::getTaskPlanStatus, TaskPlanStatusEnum.DOING.getCode())
                .eq(BaseDispatchTask::getIsDelete, DelFlagEnum.NORMAL.getCode());
        return getOne(queryWrapper);
    }

    @Override
    public BaseDispatchTask getByTaskNo(String taskNo) {
        QueryWrapper<BaseDispatchTask> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(BaseDispatchTask::getTaskNo, taskNo)
                .eq(BaseDispatchTask::getIsDelete, DelFlagEnum.NORMAL.getCode());
        return getOne(queryWrapper);
    }

    @Override
    public TaskForCreateProductVo getNowTaskForCreateProduct() {
        QueryWrapper<BaseDispatchTask> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(BaseDispatchTask::getTaskPlanStatus, TaskPlanStatusEnum.DOING.getCode())
                .eq(BaseDispatchTask::getIsDelete, DelFlagEnum.NORMAL.getCode());
        BaseDispatchTask baseDispatchTask = getOne(queryWrapper);
        if (baseDispatchTask == null) {
            log.warn("当前没有进行中的任务");
            return null;
        }
        TaskForCreateProductVo taskForCreateProductVo = new TaskForCreateProductVo();
        taskForCreateProductVo.setTaskId(baseDispatchTask.getTaskId());
        taskForCreateProductVo.setOrderId(baseDispatchTask.getOrderId());
        taskForCreateProductVo.setMaterialModel(baseDispatchTask.getMaterialModel());
        taskForCreateProductVo.setMaterialCode(baseDispatchTask.getMaterialCode());
        taskForCreateProductVo.setMaterialName(baseDispatchTask.getMaterialName());
        taskForCreateProductVo.setIssuer(baseDispatchTask.getIssuer());
        return taskForCreateProductVo;
    }

    @Override
    public void productTransfer() {
        log.debug("开始转序...");
        BaseDispatchTask doingTask = getDoingTask();
        MesMaterialDistributionRequest distribution = new MesMaterialDistributionRequest();
        distribution.setCode(doingTask.getTaskNo());
        distribution.setOrderID(doingTask.getWorkOrderNo());
        distribution.setTaskID(doingTask.getTaskId());
        distribution.setDeliveryType(MesMaterialDistributionRequest.DeliveryTypeEnum.TRANSFER.getCode());
        // 产品的物料编码
        distribution.setMaterial(doingTask.getMaterialCode());
        LoginUser loginUser =null;
        try {
            loginUser=SecurityUtils.getLoginUser();
        }catch (Exception e) {
            e.printStackTrace();

        }

        distribution.setCreator(loginUser==null?"":SecurityUtils.getLoginUser().getUser().getUserName());

        distribution.setEndLocation(locationConfig.getProductTransfer());
        distribution.setCreateTime(new Date());
        distribution.setLastModifiedTime(new Date());
        log.debug("转序:{}", distribution);
        MesResult<Void> mesResult = mesRequestService.materialDistribution(distribution);
        if (!mesResult.isSuccess()) {
            log.error("产品转序失败， 发生内容，{} 返回内容：{}", distribution, mesResult);
            return;
        }
        log.info("产品转序结果：{}", mesResult);
    }

    @Override
    public void callMesFinishTask(BaseDispatchTask doingTask) {
        MesFinishTaskRequest finishTask = new MesFinishTaskRequest();
        MesFinishTaskRequest.OrderInfo orderInfo = new MesFinishTaskRequest.OrderInfo();
        orderInfo.setEmployee(doingTask.getIssuer());
        orderInfo.setOrderID(doingTask.getOrderId());
        orderInfo.setTaskId(doingTask.getTaskId());
        orderInfo.setQuantity(doingTask.getCompletedQty());
        orderInfo.setWorkingHours(doingTask.getWorkingHours());
        finishTask.setData(Arrays.asList(orderInfo));
        MesResult<Void> mesResult = mesRequestService.finishTask(finishTask);
        if (!mesResult.isSuccess()) {
            log.error("同步mes数据异常，任务完工与工时汇报接口,发送内容：{},返回内容：{}", finishTask, mesResult);
            return;
        }
        log.info("同步mes数据成功，任务完工与工时汇报接口，返回内容：{}", mesResult);
    }


    public List<BaseDispatchTask> getTaskListByOrderId(String orderId) {
        QueryWrapper<BaseDispatchTask> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(BaseDispatchTask::getOrderId, orderId)
                .eq(BaseDispatchTask::getIsDelete, DelFlagEnum.NORMAL.getCode());

        return list(queryWrapper);
    }

    @Override
    public BaseDispatchTask getLastTask() {
        QueryWrapper<BaseDispatchTask> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .in(BaseDispatchTask::getTaskPlanStatus, TaskPlanStatusEnum.DOING.getCode(), TaskPlanStatusEnum.PAUSE.getCode(), TaskPlanStatusEnum.FINISHED.getCode())
                .eq(BaseDispatchTask::getIsDelete, DelFlagEnum.NORMAL.getCode())
                .orderByDesc(BaseEntity::getUpdateTime);
        return this.getBaseMapper().getLastTask(queryWrapper);
    }

    @Override
    public List<ProductQualificationRate> yieldAcquisition(DeviceFaultDto deviceFaultDto) {
        List<BaseProductInfo> list = baseProductInfoService.list(new LambdaQueryWrapper<BaseProductInfo>()
                .ge(deviceFaultDto.getStartTime() != null, BaseProductInfo::getEndTime, deviceFaultDto.getStartTime())
                .le(deviceFaultDto.getEndTime() != null, BaseProductInfo::getEndTime, deviceFaultDto.getEndTime()));
        ArrayList<ProductQualificationRate> arrayList = new ArrayList<>();
        ArrayList<String> productNameList = baseProductInfoService.getProductNameList();
        Map<String, List<BaseProductInfo>> baseProductInfoMap;
        if (list != null && list.size() != 0) {
            baseProductInfoMap = list.stream()
                    .collect(Collectors.groupingBy(BaseProductInfo::getProductName));
        } else {
            baseProductInfoMap = new HashMap<>();
        }
        productNameList.forEach(productName -> {
            ProductQualificationRate productQualificationRate = new ProductQualificationRate();
            if (baseProductInfoMap.containsKey(productName)) {
                List<BaseProductInfo> v = baseProductInfoMap.get(productName);
                long count = v.stream().filter(s -> s.getIsQualified()).count();
                productQualificationRate.setProductName(productName);
                productQualificationRate.setAcceptanceNumber((int) count);
                productQualificationRate.setBelowStandardNumber((int) (v.size() - count));
            } else {
                productQualificationRate.setProductName(productName);
                productQualificationRate.setAcceptanceNumber(0);
                productQualificationRate.setBelowStandardNumber(0);
            }
            arrayList.add(productQualificationRate);
        });

        return arrayList;
    }

    @Override
    public ActualProductionPlanning actualProductionPlanning(DeviceFaultDto deviceFaultDto) {
        //获取当前时间段的产品
        List<BaseDispatchTask> list = list(new LambdaQueryWrapper<BaseDispatchTask>()
                .ge(deviceFaultDto.getStartTime() != null, BaseDispatchTask::getPlanEndTime, deviceFaultDto.getStartTime())
                .le(deviceFaultDto.getEndTime() != null, BaseDispatchTask::getPlanEndTime, deviceFaultDto.getEndTime()));
        List<BaseDispatchTask> taskList = list(new LambdaQueryWrapper<BaseDispatchTask>()
                .ge(deviceFaultDto.getStartTime() != null, BaseDispatchTask::getTaskStartTime, deviceFaultDto.getStartTime()));
//                .le(deviceFaultDto.getEndTime() != null, BaseDispatchTask::getTaskEndTime, deviceFaultDto.getEndTime()));
        ActualProductionPlanning actualProductionPlanning = new ActualProductionPlanning();
        //判断这段时间的内容集合是否为空
        if (!list.isEmpty()||!taskList.isEmpty()) {
            //集合通过stream流获取这段数据的派工数量的总和
            Double dispatchSum = list.stream().mapToDouble(s -> {
                if (s.getDispatchQty() != null) {
                    return s.getDispatchQty().doubleValue();
                }
                return 0;
            }).summaryStatistics().getSum();
            //生产计划
            actualProductionPlanning.setProductionPlanning(dispatchSum.toString());
            Double completedSum = taskList.stream().mapToDouble(s -> {
                if (s.getCompletedQty() != null) {
                    return s.getCompletedQty().doubleValue();
                }
                return 0;
            }).summaryStatistics().getSum();
            //实际生产
            actualProductionPlanning.setActualProduction(completedSum.toString());
            //判断派工数量是否为 0
            if (completedSum != 0) {
                //获取当前的产品的 id
                List<String> idList = taskList.stream().map(s -> s.getId().toString()).collect(Collectors.toList());
                //根据产品 id 与是否合格获取当前不合格数量
                int count = baseProductInfoService.count(new LambdaQueryWrapper<BaseProductInfo>()
                        .in(BaseProductInfo::getBaseDispatchTaskId, idList)
                        .ne(BaseProductInfo::getIsQualified, 1));
                //不良品
                actualProductionPlanning.setDefectiveProducts(String.valueOf(count));
                // 通过已完成数量/派工数量*100获取当前完成率
                String rateOfCompletion = new BigDecimal(completedSum).divide(new BigDecimal(completedSum+count), 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).toPlainString();
                actualProductionPlanning.setRateOfCompletion(rateOfCompletion);
            }
        }
        return actualProductionPlanning;

    }
}




